package com.rem.redis.service;


import cn.hutool.core.thread.ThreadUtil;
import org.redisson.api.RLocalCachedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author Rem
 * @date 2022/8/12
 */
@Service
public class RedissonCacheService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RLocalCachedMap<String, Object> localCache;

    /**
     * 修改/新增
     *
     * @return
     */
    public int update() {
        // 1. 添加数据
        for (int i = 0; i < 1000; i++) {
            String key = "key" + i;
            localCache.fastPut(key, "v0"); // 此处新增会同步到本地缓存，推荐使用（fastPut）：fastPut不会返回旧值，put会取一次旧值返回
//          localCache.fastPut(key, "v0"); // 同步存值
//          localCache.fastPutAsync(key, "v0"); // 异步存值
        }

        // 2. 查询本地缓存是否放进去
        logger.info(">>>>>>>>>>local cached size: {}", localCache.cachedValues().size());

        return localCache.cachedValues().size();
    }

    /**
     * 批量压力测试
     *
     * @return
     */
    public void addBatch() {

        ThreadUtil.concurrencyTest(20, () -> {
            long startTime = System.currentTimeMillis();

            Map<String, Object> map = new HashMap<>();
            // 1. 添加数据
            for (int i1 = 0; i1 < 1000; i1++) {
                String key = "key" + (1 + Math.random() * 10000);
                map.put(key, "v" + i1);
            }

            localCache.putAllAsync(map);//异步存值

            // 2. 查询本地缓存是否放进去
            long endTime = System.currentTimeMillis();
            logger.info(">>>>>>>>>>local cached size: {}, time: {}ms, currentThreadId: {}", localCache.cachedValues().size(), endTime - startTime, Thread.currentThread().getId());

            try {
                TimeUnit.MILLISECONDS.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 批量新增和单个新增效率比对
     *
     * @return
     */
    public int add() {
        long startTime = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();

        // 1. 添加数据
        for (int i = 0; i < 1000; i++) {
            String key = "key" + i;
            // 此处新增会同步到本地缓存，推荐使用（fastPut）：fastPut不会返回旧值，put会取一次旧值返回
//          localCache.put(key, "v"+i);
//          localCache.fastPut(key, "v"+i);
            localCache.fastPutAsync(key, "v" + i); // 异步存值

            map.put(key, "v" + i);
        }

        // 2. 查询本地缓存是否放进去
        logger.info(">>>>>>>>>>local cached size: {}", localCache.cachedValues().size());
        long endTime = System.currentTimeMillis();
        logger.info(">>>>>>>>>>fastPutAsync time: {}ms", endTime - startTime);

        localCache.putAllAsync(map);
        long endTime2 = System.currentTimeMillis();
        logger.info(">>>>>>>>>>putAllAsync time: {}ms", endTime2 - endTime);

        return localCache.cachedValues().size();
    }

    /**
     * 查询
     *
     * @return
     */
    public int get() {
        // 1. 查询本地缓存是否预热，如果没有调用get方法会自动加到本地缓存
        logger.info(">>>>>>>>>>local cached size: {}", localCache.cachedValues().size());

        long startTime = System.currentTimeMillis();

        // 2. 查询数据
        for (int i = 0; i < 1000; i++) {
            String key = "key" + i;
            Object value = localCache.get(key); //优先查本地缓存，没有再查redis，然后放回本地缓存
            logger.info(">>>>>>>>>>Get key:{}, value: {}", key, value);

            //为了验证淘汰策略，多get一次
//          if (i % 5 == 0) {
//              localCache.get(key);
//          }
        }

        long endTime = System.currentTimeMillis();
        logger.info(">>>>>>>>>>local cached size: {}, time: {}ms, ", localCache.cachedValues().size(), endTime - startTime);

        return localCache.cachedValues().size();
    }

    /**
     * 刷新本地缓存
     *
     * @return
     */
    public int refresh() {
        // 1. 清空本地缓存
        localCache.clearLocalCache();
        // 2. 数据预加载
        localCache.preloadCache();
        // 3.  查看本地cache size
        logger.info(">>>>>>>>>>local cached size: {}", localCache.cachedValues().size());
        return localCache.cachedValues().size();
    }

}